import Path from "path";
import Fs from "fs-extra";
import axios, { AxiosRequestConfig } from "axios";
import { PROJECT_DIR } from "./misc";

/**
 * 下载文件的函数
 * @param url 下载的url，用于传给axios
 * @param path 下载的文件路径
 * @param config axios的配置
 */
export async function downloadFile(
  url: string,
  path: string,
  config: AxiosRequestConfig = {}
): Promise<void> {
  const res = await axios.get(url, { responseType: "arraybuffer", ...config });
  const { data } = res;
  const buf = Buffer.from(data as ArrayBuffer);
  const directory = Path.dirname(path);
  Fs.ensureDirSync(directory);
  Fs.writeFileSync(path, buf);
}

/**
 * 当前是否被electron-builder打包
 * app.asar.unpacked 或 在app.asar里
 */
export const IS_IN_ASAR = /resources[/\\]app\.asar(\.unpack)?$/i.test(
  PROJECT_DIR
);

/**
 * 如果electron未打包，则为工程目录，如果打包，则返回.exe所在目录
 */
export const APP_DIRNAME = IS_IN_ASAR
  ? Path.resolve(PROJECT_DIR, "..", "..")
  : PROJECT_DIR;

/**
 * 如果在nodeJS或者electron开发环境下，返回相对于工程目录的的路径
 * 如果electron已经打包，返回相对于.exe文件所在目录的路径
 * @param relativePath 相对路径
 * @param mode 路径模式
 * @returns 返回创建的路径
 */
export function dir(
  relativePath: string[] | string = "database",
  mode?: "Dir" | "File" | "dir" | "file"
): string {
  const ensure = (result: string) => {
    if (mode) {
      // 如果指定了mode
      if (/dir/i.test(mode)) {
        // 并且
        Fs.ensureDirSync(result); //
      } else {
        Fs.ensureFileSync(result);
      }
    }
    return result;
  };
  if (typeof relativePath === "string") {
    relativePath = relativePath.replace(/^\//, ""); // 如果开头是/，则去掉
    const result = Path.join(APP_DIRNAME, relativePath);
    return ensure(result); // 确定该result
  } else {
    let result = APP_DIRNAME;
    for (let path of relativePath) {
      path = path.replace(/^\//, ""); // 如果开头是/，则去掉
      result = Path.resolve(result, path);
    }
    return ensure(result); // 确定该result
  }
}

export type InjectScriptOptions =
  | /**要写入的script */
  string
  | {
      /**
       * 要注入的script
       */
      script: string;
    }
  | {
      /**
       * 要注入script的source
       */
      src: string;
    }
  | {
      /**
       * 要注入的script的文件位置
       */
      filePath: string;
    };
/**
 * 向webContents注入script
 * @param injection 向webContents注入的内容
 */
export function injectScript(injection: string | InjectScriptOptions): void {
  const scriptElement = document.createElement("script");
  scriptElement.type = "text/javascript";
  if (typeof injection === "string") {
    let script: string = injection;
    scriptElement.appendChild(document.createTextNode(script));
  } else {
    // @ts-ignore
    const { script, src, filePath }: InjectScriptOptions = injection;
    if (script) {
      scriptElement.appendChild(document.createTextNode(script));
    } else if (src) {
      scriptElement.src = src;
    } else if (filePath && Fs.pathExistsSync(filePath)) {
      const js = Fs.readFileSync(filePath, { encoding: "utf-8" });
      scriptElement.appendChild(document.createTextNode(js));
    }
  }
  document.body.appendChild(scriptElement);
}

export interface InjectCssOptions {
  /**
   * 要注入的css内容
   */
  css?: string;
  /**
   * 要注入的hef
   */
  href?: string;
  /**
   * 要注入的css文件地址
   */
  filePath?: string;
}

/**
 * 向webContents注入css
 * @param option 向webContents注入的css选项
 */
export function injectCss({
  css = "",
  href = "",
  filePath = "",
}: InjectCssOptions) {
  const head = document.getElementsByTagName("head")[0];
  if (href) {
    const cssElement = document.createElement("link");
    cssElement.setAttribute("rel", "stylesheet");
    cssElement.setAttribute("media", "all");
    cssElement.setAttribute("type", "text/css");
    cssElement.setAttribute("href", href);
    head.appendChild(cssElement);
  } else {
    const styleElement = document.createElement("style");
    const content = css || Fs.readFileSync(filePath, { encoding: "utf-8" });
    styleElement.appendChild(document.createTextNode(content));
    head.appendChild(styleElement);
  }
}
